package ru.osu.acm.testing.beans;

import ru.osu.acm.common.entities.Submission;
import ru.osu.acm.common.config.Config;
import ru.osu.acm.testing.Utils;

import javax.annotation.Resource;
import javax.sql.DataSource;
import javax.faces.context.FacesContext;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.TreeSet;

/**
 * User: Integra
 * Date: 31.08.2009
 * Time: 16:17:46
 */
public class MonitorBean {
    @Resource(name = Config.jndi)
    private DataSource source;
    private int selectedContest;
    private MonitorItem[] monitorItems = null;
    private ArrayList<String> letters = new ArrayList<String>();
    private String emptyString;


    public void initialize() {
        ArrayList<String> users = new ArrayList<String>();
        ArrayList<Integer> usersId = new ArrayList<Integer>();
        letters.clear();
        boolean ok = false;
        selectedContest = getSelectedContest();
        int cnt = 0;
        try {
            Connection conn = source.getConnection();
            try {
                //PreparedStatement statement = conn.prepareStatement("select person.id, concat(person.firstname,' ', person.secondname)" +
                PreparedStatement statement = conn.prepareStatement("select person.id, person.secondname" +
                        " from person, contestperson where contestperson.contest = ? and contestperson.person=person.id" +
                        " union select team.id, team.teamname from team, contestteam " +
                        "where  contestteam.contest= ? and contestteam.team=team.id");
                statement.setInt(1, selectedContest);
                statement.setInt(2, selectedContest);
                ResultSet resultSet = statement.executeQuery();
                while (resultSet.next()) {
                    users.add(resultSet.getString(2));
                    usersId.add(resultSet.getInt(1));
                    cnt++;
                    ok = true;
                }
                resultSet.close();
                statement.close();
                if (ok) {
                    statement = conn.prepareStatement("select contestproblem.problemindex from contestproblem where contestproblem.contest = ?");
                    statement.setInt(1, selectedContest);
                    resultSet = statement.executeQuery();
                    int problemCount = 0;
                    while (resultSet.next()) {
                        letters.add(Utils.getProblemLetter(resultSet.getInt(1)));
                        problemCount++;
                    }
                    monitorItems = new MonitorItem[cnt];
                    int i = 0;
                    for (String s : users) {
                        String[] problem = new String[problemCount];
                        Arrays.fill(problem, "-");
                        monitorItems[i] = new MonitorItem(usersId.get(i), i + 1, s, problem, 0, 0);
                        i++;
                    }
                }
            }
            finally {
                conn.close();
            }
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public ArrayList<String> getLetters() {
        return letters;
    }

    public void setLetters(ArrayList<String> letters) {
        this.letters = letters;
    }

    public int getSelectedContest() {
        FacesContext fc = FacesContext.getCurrentInstance();
        DataBean db = (DataBean) fc.getApplication().getVariableResolver().resolveVariable(fc, "data");
        return db.getSelectedContest();
    }

    public void setSelectedContest(int selectedContest) {
        this.selectedContest = selectedContest;
    }


    public MonitorItem[] getMonitorItems() {
      /*  int lastselectedContest = selectedContest;
        selectedContest = getSelectedContest();
        if (monitorItems == null) {
            initialize();
        } else if (selectedContest != lastselectedContest) {
            initialize();
        }
        */
        initialize();
        TreeSet<Integer> badStatus = new TreeSet<Integer>();
    //    badStatus.add(5);  //is compilier error -1??
        badStatus.add(6);
        badStatus.add(7);
        badStatus.add(8);
        badStatus.add(9);
        badStatus.add(10);
        for (MonitorItem item : monitorItems) {
            String who="";
            String[] init= new String[item.getResults().length];
            Arrays.fill(init,"-");
            item.setResults(init);
            try {
                Connection conn = source.getConnection();
                try {
                    //PreparedStatement statement= conn.prepareStatement("select concat(person.firstname,' ', person.secondname) from person where person.id =?");
                    PreparedStatement statement= conn.prepareStatement("select person.secondname from person where person.id =?");
                    statement.setInt(1,item.getId());
                    ResultSet resultSet= statement.executeQuery();
                    if (resultSet.next() && resultSet.getString(1).compareTo(item.getName())==0){              
                        who = "person";
                    }
                    else
                        who = "team";
                    resultSet.close();
                    statement.close();
                    statement = conn.prepareStatement("select submission.id, contestproblem.problemindex, submission.status, submission.submitted , contest.startdate from submission, contestproblem, contest " +
                            "where submission.contest = ? and submission."+who+" = ? " +
                            "and contestproblem.contest=? and contestproblem.problem=submission.problem  and contest.id = submission.contest" +
                            " order by submission.id asc");
                    statement.setInt(1, selectedContest);
                    statement.setInt(2, item.getId());
                    statement.setInt(3,selectedContest);
                    resultSet = statement.executeQuery();
                    while (resultSet.next()){
                        int curIndex= letters.indexOf(Utils.getProblemLetter(resultSet.getInt(2)));
                        int curStatus = resultSet.getInt(3);
                        if (item.getResults()[curIndex].startsWith("-"))
                        {
                            int curResult;
                            String s=item.getResults()[curIndex].substring(1,item.getResults()[curIndex].length());
                             if (s.compareTo("")==0)
                                 curResult=-1;
                            else
                                 curResult = Integer.parseInt(s);
                             if (badStatus.contains(curStatus)){
                                 if (curResult==-1)
                                    curResult=1;
                                 else
                                     curResult++;
                                 item.getResults()[curIndex]="-"+Integer.toString(curResult);
                             }
                             else
                             if (curStatus==4) //accepted
                             {
                                 if (item.getId()==42)
                                    s=s;
                                 s= curResult==-1 ? "" :Integer.toString(curResult);
                                 item.getResults()[curIndex]="+"+s;
                                 item.setTotal(item.getTotal()+1);
                                 java.sql.Timestamp begin = resultSet.getTimestamp(5);
                                 java.sql.Timestamp currentTime = resultSet.getTimestamp(4);
                                 long penalty = curResult==-1 ? 0:curResult;
                                 long time = (currentTime.getTime()-begin.getTime())/60000+penalty*20;
                                 item.setTime(time+item.getTime());
                                 //TODO: add penalty time
                             }
                        }

                    }

                }
                finally {
                    conn.close();
                }
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }

        Arrays.sort(monitorItems);
        int place=1;
        for (MonitorItem mI:monitorItems){
            mI.setPlace(place++);
        }
        return monitorItems;
    }

    public void setMonitorItems(MonitorItem[] monitorItems) {
        this.monitorItems = monitorItems;
    }

    public String getNameOfTheContest() {
        int currentContest = getSelectedContest();
        try {
            Connection conn = source.getConnection();
            try {
                PreparedStatement statement = conn.prepareStatement("select contest.contestname from contest where contest.id=?");
                statement.setInt(1, currentContest);
                ResultSet resultSet = statement.executeQuery();
                if (resultSet.next()) {
                    return "Monitor of the " + resultSet.getString(1);
                }
                statement.close();
                resultSet.close();
            }
            finally {
                conn.close();
            }
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        return "Error";
    }

    public String getEmptyString() {
        return "";
    }

    public void setEmptyString(String emptyString) {
    }
}
